from flask import Blueprint, request, jsonify, send_file
from models import db, RewardPunishment, Employee
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from io import BytesIO
from datetime import datetime, date

reward_punishment_bp = Blueprint('reward_punishment', __name__)

def get_common_styles():
    header_font = Font(bold=True, color="FFFFFF")
    header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
    centered_alignment = Alignment(horizontal="center", vertical="center")
    thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))

    header_style = {
        'font': header_font,
        'fill': header_fill,
        'alignment': centered_alignment,
        'border': thin_border
    }
    content_style = {
        'alignment': centered_alignment,
        'border': thin_border
    }
    return header_style, content_style

def adjust_column_width(sheet, data):
    for col in range(1, sheet.max_column + 1):
        max_length = 0
        column = [cell.value for cell in sheet[chr(64 + col)]]
        for cell in column:
            try:
                if isinstance(cell, datetime):
                     cell = cell.strftime('%Y-%m-%d %H:%M:%S')
                elif isinstance(cell, date):
                     cell = cell.strftime('%Y-%m-%d')
                elif cell is None:
                    cell = ''
                cell = str(cell)

                # 估算中文字符宽度
                chinese_chars = sum([1 for char in cell if '\u4e00' <= char <= '\u9fff'])
                english_chars = len(cell) - chinese_chars
                # 假设一个中文字符宽度约等于两个英文字符
                length = english_chars + chinese_chars * 2

                if length > max_length:
                    max_length = length
            except:
                pass

        adjusted_width = (max_length + 2) * 1.2 # Add a little padding
        sheet.column_dimensions[chr(64 + col)].width = adjusted_width

@reward_punishment_bp.route('/api/reward-punishments/export/excel', methods=['GET'])
def export_reward_punishments_excel():
    # Fetch all reward/punishment records, joining with Employee to get name
    records = db.session.query(RewardPunishment, Employee).join(Employee).order_by(RewardPunishment.date.desc()).all()

    # Define fields to export based on the rule, plus employee_name
    fields = [
        'employee_name',
        'type',
        'reason',
        'date',
    ]

    # Define headers in Chinese
    headers = {
        'employee_name': '员工姓名',
        'type': '奖惩类型',
        'reason': '奖惩原因',
        'date': '奖惩时间',
    }

    workbook = Workbook()
    sheet = workbook.active
    sheet.title = "奖惩列表"

    header_style, content_style = get_common_styles()

    # Write headers
    header_row = [headers[field] for field in fields]
    sheet.append(header_row)
    for col_num, cell in enumerate(sheet[1]):
        cell.font = header_style['font']
        cell.fill = header_style['fill']
        cell.alignment = header_style['alignment']
        cell.border = header_style['border']

    # Write data rows
    for record, employee in records:
        row_data = []
        # Manually extract data based on fields and the joined objects
        for field in fields:
            if field == 'employee_name':
                value = employee.name if employee else None
            else:
                value = getattr(record, field, None)

            # Format date field if necessary
            if field == 'date' and isinstance(value, str):
                 # Assuming the date is stored as a string in 'YYYY-MM-DD' format
                try:
                    value = date.fromisoformat(value)
                except ValueError:
                    pass # Keep original string if parsing fails

            row_data.append(value)

        sheet.append(row_data)
        # Apply content style to the newly added row
        for cell in sheet[sheet.max_row]:
             cell.alignment = content_style['alignment']
             cell.border = content_style['border']

    # Adjust column widths
    # Note: adjust_column_width is designed for sheets directly appended with data. Passing 'records' might not work as expected.
    # Let's pass the sheet itself for width adjustment.
    adjust_column_width(sheet, sheet)

    # Save to a byte stream
    excel_buffer = BytesIO()
    workbook.save(excel_buffer)
    excel_buffer.seek(0)

    return send_file(
        excel_buffer,
        as_attachment=True,
        download_name='奖惩列表.xlsx',
        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    )

@reward_punishment_bp.route('/api/employees/<int:employee_id>/reward_punishments', methods=['GET'])
def get_reward_punishments(employee_id):
    records = RewardPunishment.query.filter_by(employee_id=employee_id).order_by(RewardPunishment.date.desc()).all()
    return jsonify([r.to_dict() for r in records])

@reward_punishment_bp.route('/api/employees/<int:employee_id>/reward_punishments', methods=['POST'])
def create_reward_punishment(employee_id):
    data = request.get_json()
    record = RewardPunishment(
        employee_id=employee_id,
        type=data.get('type'),
        reason=data.get('reason'),
        date=data.get('date')
    )
    db.session.add(record)
    db.session.commit()
    return jsonify({'message': '创建成功', 'id': record.id}), 201

@reward_punishment_bp.route('/api/employees/<int:employee_id>/reward_punishments/<int:id>', methods=['PUT'])
def update_reward_punishment(employee_id, id):
    record = RewardPunishment.query.filter_by(id=id, employee_id=employee_id).first_or_404()
    data = request.get_json()
    record.type = data.get('type', record.type)
    record.reason = data.get('reason', record.reason)
    record.date = data.get('date', record.date)
    db.session.commit()
    return jsonify({'message': '修改成功'})

@reward_punishment_bp.route('/api/employees/<int:employee_id>/reward_punishments/<int:id>', methods=['DELETE'])
def delete_reward_punishment(employee_id, id):
    record = RewardPunishment.query.filter_by(id=id, employee_id=employee_id).first_or_404()
    db.session.delete(record)
    db.session.commit()
    return jsonify({'message': '删除成功'}) 